package nz.ac.massey.groupproject.ecs2;

// TODO should we replace Position etc with vec2?
public final class Vec2l {
	public final long x, y;

	public Vec2l(long xx, long yy) { x = xx;        y = yy;        }
	public Vec2l(int  xx, int  yy) { x = (long) xx; y = (long) yy; }

	// TODO hashCode
	public final boolean equals(Vec2l v) {  return x == v.x && y == v.y;  }

	public final Vec2l neg()         {  return new Vec2l(-x, -y);                 }
	public final Vec2l add (Vec2l v) {  return new Vec2l(  x + v.x,  y + v.y  );  }
	public final Vec2l sub (Vec2l v) {  return new Vec2l(  x - v.x,  y - v.y  );  }
	//public final Vec2l mul (long c)  {  return new Vec2l(   c * x,    c * y   );  }
	public final long cprod(Vec2l v) {  return  x * v.y  -  y * v.x;  }
	public final long dot  (Vec2l v) {  return  x * v.x  +  y * v.y;  }
	public final long square()       {  return  x * x    +  y * y;    }




	// vec2{ dirx[i], diry[i] } points to the i-th direction
	public static final long[] OCTADIR_X = { 1, 1, 0, -1, -1, -1,  0,  1 };
	public static final long[] OCTADIR_Y = { 0, 1, 1,  1,  0, -1, -1, -1 };

	// return 0,1,2,3,...,7 if vector points to a orthogonal or diagonal direction (i.e. multiple of 45°)
	// return -1 otherwise
	//
	// 0 points to the right, 1 points to upper-right, ...
	public final int getOctadir() {
		if      (x == 0)    return y > 0 ? 2 : 6;
		else if (y == 0)    return x > 0 ? 0 : 4;
		else if (x == y)    return y > 0 ? 1 : 5;
		else if (x == -y)   return y > 0 ? 3 : 7;
		return -1;
	}

	// return the direction rounded to one of 16 primary directions (i.e. nearest multiple of 22.5°).
	// Not very accurate
	// break ties arbitrarily (but deterministically)
	//
	// Primary directions are represented by 0 to 15, with 0 pointing towards the right, and increasing
	// counter-clockwise (so this encoding agrees with angles in our coordinate system).
	public final int roundToHexadir() {
		long xx = x, yy = y;      boolean x, y; // prevent accidental usage of data field
		int ans = 0;

		// limit to upper half-plane and x axis
		if (yy < 0) {
			xx *= -1;
			yy *= -1;
			ans += 8;
		}
		// limit to northeast quadrant and positive half-axes
		if (xx < 0) {
			long tmp = -xx;   xx = yy;   yy = tmp;
			ans += 4;
		}

		// test dir 0,1,2,3,4
		if (yy * 1000000 < 668179 * xx) {                        // deg < 33.75           tan(33.75°) ≈ 6681786379192989e-16
			if (yy * 1000000 > 198912 * xx) ans += 1;        // deg > 11.25           tan(11.25°) ≈ 198912367379658e-15

		} else if (yy * 198912 >= 1000000 * xx) {                // deg >= 78.75
			ans += 4;

		} else  ans += (xx * 1000000 >= 668179 * yy) ? 2 : 3;    // deg <= 56.25

		return ans % 16;
	}
}
